/**
 *
 */
package org.shark.jdbcTemplateTool;

import static org.shark.jdbcTemplateTool.utils.CatalogUtils.changeCatalog;

import java.util.List;
import java.util.Map;

import org.shark.jdbcTemplateTool.impl.ReturnIdPreparedStatementCreator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

/**
 * @author lenovo
 * @description
 * @date 2016年8月15日
 */
public class JdbcTemplateProxy {

    private JdbcTemplate jdbcTemplate;
    
    private NamedParameterJdbcTemplate namedJdbcTemplate;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

//	private static String changIn

    //------------- select -----------------//

    public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return jdbcTemplate.query(sql, rowMapper);
        } catch (DataAccessException e) {
            logger.error("Error SQL: " + sql);
            throw e;
        }
    }
    
    public int execUpdateSql(String sql, Map<String, ?> paramMap) {
    	return namedJdbcTemplate.update(sql, paramMap);
    }
    
    public int execUpdateSql(String sql, Object[] args) {
    	return jdbcTemplate.update(sql, args);
    }

    public <T> List<T> query(String sql, Object[] params, RowMapper<T> rowMapper) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return jdbcTemplate.query(sql, params, rowMapper);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (Object p : params) {
                sb.append(p + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }
    
    public <T> List<T> query(String sql, Map<String, Object> params, RowMapper<T> rowMapper) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return namedJdbcTemplate.query(sql, params, rowMapper);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (String key : params.keySet()) {
                sb.append(params.get(key) + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }

    public Map<String, Object> queryForMap(String sql) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return jdbcTemplate.queryForMap(sql);
        } catch (DataAccessException e) {
            logger.error("Error SQL: " + sql);
            throw e;
        }
    }

    public Map<String, Object> queryForMap(String sql, Object[] params) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return jdbcTemplate.queryForMap(sql, params);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (Object p : params) {
                sb.append(p + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }

    public Map<String, Object> queryForMap(String sql, Map<String, Object> params) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return namedJdbcTemplate.queryForMap(sql, params);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (String p : params.keySet()) {
                sb.append(params.get(p) + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }

    //------------ update ------------------//
    public int update(String sql, Object[] params) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            int ret = jdbcTemplate.update(sql, params);
            return ret;
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (Object p : params) {
                sb.append(p + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }

    //------------ update ------------------//
    public int update(String sql, Map<String, Object> params) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            int ret = namedJdbcTemplate.update(sql, params);
            return ret;
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (String p : params.keySet()) {
                sb.append(params.get(p) + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }
    }

    public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        try {
            return jdbcTemplate.batchUpdate(sql, pss);
        } catch (DataAccessException e) {
            logger.error("Error SQL: " + sql);
            throw e;
        }
    }

    /**
     * insert a row with auto increament id
     *
     * @param sql
     * @param params
     * @param autoGeneratedColumnName
     * @return
     * @throws DataAccessException
     */
    public int insert(String sql, Object[] params, String autoGeneratedColumnName)
            throws DataAccessException {
        //dynamic change catalog name
        sql = changeCatalog(sql);

        ReturnIdPreparedStatementCreator psc = new ReturnIdPreparedStatementCreator(sql, params, autoGeneratedColumnName);
        KeyHolder keyHolder = new GeneratedKeyHolder();
        try {
            jdbcTemplate.update(psc, keyHolder);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (Object p : params) {
                sb.append(p + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }

        return keyHolder.getKey().intValue();
    }
    
    public int insert(String sql, Map<String, Object> params, String autoGeneratedColumnName) {
        //dynamic change catalog name
        sql = changeCatalog(sql);
        SqlParameterSource sqlparams = new MapSqlParameterSource(params);
        KeyHolder keyHolder = new GeneratedKeyHolder();
        try {
        	namedJdbcTemplate.update(sql, sqlparams, keyHolder);
        } catch (DataAccessException e) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (String p : params.keySet()) {
                sb.append(params.get(p) + " | ");
            }
            sb.append("]");
            logger.error("Error SQL: " + sql + " Params: " + sb.toString());
            throw e;
        }

        return keyHolder.getKey().intValue();
    }
    


    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
        this.namedJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
    }
}
